home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  13.4 KB  |  549 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // cl.input.c  -- builds an intended movement command to send to the server
  21.  
  22. #include "client.h"
  23.  
  24. cvar_t    *cl_nodelta;
  25.  
  26. extern    unsigned    sys_frame_time;
  27. unsigned    frame_msec;
  28. unsigned    old_sys_frame_time;
  29.  
  30. /*
  31. ===============================================================================
  32.  
  33. KEY BUTTONS
  34.  
  35. Continuous button event tracking is complicated by the fact that two different
  36. input sources (say, mouse button 1 and the control key) can both press the
  37. same button, but the button should only be released when both of the
  38. pressing key have been released.
  39.  
  40. When a key event issues a button command (+forward, +attack, etc), it appends
  41. its key number as a parameter to the command so it can be matched up with
  42. the release.
  43.  
  44. state bit 0 is the current state of the key
  45. state bit 1 is edge triggered on the up to down transition
  46. state bit 2 is edge triggered on the down to up transition
  47.  
  48.  
  49. Key_Event (int key, qboolean down, unsigned time);
  50.  
  51.   +mlook src time
  52.  
  53. ===============================================================================
  54. */
  55.  
  56.  
  57. kbutton_t    in_klook;
  58. kbutton_t    in_left, in_right, in_forward, in_back;
  59. kbutton_t    in_lookup, in_lookdown, in_moveleft, in_moveright;
  60. kbutton_t    in_strafe, in_speed, in_use, in_attack;
  61. kbutton_t    in_up, in_down;
  62.  
  63. int            in_impulse;
  64.  
  65.  
  66. void KeyDown (kbutton_t *b)
  67. {
  68.     int        k;
  69.     char    *c;
  70.     
  71.     c = Cmd_Argv(1);
  72.     if (c[0])
  73.         k = atoi(c);
  74.     else
  75.         k = -1;        // typed manually at the console for continuous down
  76.  
  77.     if (k == b->down[0] || k == b->down[1])
  78.         return;        // repeating key
  79.     
  80.     if (!b->down[0])
  81.         b->down[0] = k;
  82.     else if (!b->down[1])
  83.         b->down[1] = k;
  84.     else
  85.     {
  86.         Com_Printf ("Three keys down for a button!\n");
  87.         return;
  88.     }
  89.     
  90.     if (b->state & 1)
  91.         return;        // still down
  92.  
  93.     // save timestamp
  94.     c = Cmd_Argv(2);
  95.     b->downtime = atoi(c);
  96.     if (!b->downtime)
  97.         b->downtime = sys_frame_time - 100;
  98.  
  99.     b->state |= 1 + 2;    // down + impulse down
  100. }
  101.  
  102. void KeyUp (kbutton_t *b)
  103. {
  104.     int        k;
  105.     char    *c;
  106.     unsigned    uptime;
  107.  
  108.     c = Cmd_Argv(1);
  109.     if (c[0])
  110.         k = atoi(c);
  111.     else
  112.     { // typed manually at the console, assume for unsticking, so clear all
  113.         b->down[0] = b->down[1] = 0;
  114.         b->state = 4;    // impulse up
  115.         return;
  116.     }
  117.  
  118.     if (b->down[0] == k)
  119.         b->down[0] = 0;
  120.     else if (b->down[1] == k)
  121.         b->down[1] = 0;
  122.     else
  123.         return;        // key up without coresponding down (menu pass through)
  124.     if (b->down[0] || b->down[1])
  125.         return;        // some other key is still holding it down
  126.  
  127.     if (!(b->state & 1))
  128.         return;        // still up (this should not happen)
  129.  
  130.     // save timestamp
  131.     c = Cmd_Argv(2);
  132.     uptime = atoi(c);
  133.     if (uptime)
  134.         b->msec += uptime - b->downtime;
  135.     else
  136.         b->msec += 10;
  137.  
  138.     b->state &= ~1;        // now up
  139.     b->state |= 4;         // impulse up
  140. }
  141.  
  142. void IN_KLookDown (void) {KeyDown(&in_klook);}
  143. void IN_KLookUp (void) {KeyUp(&in_klook);}
  144. void IN_UpDown(void) {KeyDown(&in_up);}
  145. void IN_UpUp(void) {KeyUp(&in_up);}
  146. void IN_DownDown(void) {KeyDown(&in_down);}
  147. void IN_DownUp(void) {KeyUp(&in_down);}
  148. void IN_LeftDown(void) {KeyDown(&in_left);}
  149. void IN_LeftUp(void) {KeyUp(&in_left);}
  150. void IN_RightDown(void) {KeyDown(&in_right);}
  151. void IN_RightUp(void) {KeyUp(&in_right);}
  152. void IN_ForwardDown(void) {KeyDown(&in_forward);}
  153. void IN_ForwardUp(void) {KeyUp(&in_forward);}
  154. void IN_BackDown(void) {KeyDown(&in_back);}
  155. void IN_BackUp(void) {KeyUp(&in_back);}
  156. void IN_LookupDown(void) {KeyDown(&in_lookup);}
  157. void IN_LookupUp(void) {KeyUp(&in_lookup);}
  158. void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
  159. void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
  160. void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
  161. void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
  162. void IN_MoverightDown(void) {KeyDown(&in_moveright);}
  163. void IN_MoverightUp(void) {KeyUp(&in_moveright);}
  164.  
  165. void IN_SpeedDown(void) {KeyDown(&in_speed);}
  166. void IN_SpeedUp(void) {KeyUp(&in_speed);}
  167. void IN_StrafeDown(void) {KeyDown(&in_strafe);}
  168. void IN_StrafeUp(void) {KeyUp(&in_strafe);}
  169.  
  170. void IN_AttackDown(void) {KeyDown(&in_attack);}
  171. void IN_AttackUp(void) {KeyUp(&in_attack);}
  172.  
  173. void IN_UseDown (void) {KeyDown(&in_use);}
  174. void IN_UseUp (void) {KeyUp(&in_use);}
  175.  
  176. void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
  177.  
  178. /*
  179. ===============
  180. CL_KeyState
  181.  
  182. Returns the fraction of the frame that the key was down
  183. ===============
  184. */
  185. float CL_KeyState (kbutton_t *key)
  186. {
  187.     float        val;
  188.     int            msec;
  189.  
  190.     key->state &= 1;        // clear impulses
  191.  
  192.     msec = key->msec;
  193.     key->msec = 0;
  194.  
  195.     if (key->state)
  196.     {    // still down
  197.         msec += sys_frame_time - key->downtime;
  198.         key->downtime = sys_frame_time;
  199.     }
  200.  
  201. #if 0
  202.     if (msec)
  203.     {
  204.         Com_Printf ("%i ", msec);
  205.     }
  206. #endif
  207.  
  208.     val = (float)msec / frame_msec;
  209.     if (val < 0)
  210.         val = 0;
  211.     if (val > 1)
  212.         val = 1;
  213.  
  214.     return val;
  215. }
  216.  
  217.  
  218.  
  219.  
  220. //==========================================================================
  221.  
  222. cvar_t    *cl_upspeed;
  223. cvar_t    *cl_forwardspeed;
  224. cvar_t    *cl_sidespeed;
  225.  
  226. cvar_t    *cl_yawspeed;
  227. cvar_t    *cl_pitchspeed;
  228.  
  229. cvar_t    *cl_run;
  230.  
  231. cvar_t    *cl_anglespeedkey;
  232.  
  233.  
  234. /*
  235. ================
  236. CL_AdjustAngles
  237.  
  238. Moves the local angle positions
  239. ================
  240. */
  241. void CL_AdjustAngles (void)
  242. {
  243.     float    speed;
  244.     float    up, down;
  245.     
  246.     if (in_speed.state & 1)
  247.         speed = cls.frametime * cl_anglespeedkey->value;
  248.     else
  249.         speed = cls.frametime;
  250.  
  251.     if (!(in_strafe.state & 1))
  252.     {
  253.         cl.viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
  254.         cl.viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
  255.     }
  256.     if (in_klook.state & 1)
  257.     {
  258.         cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
  259.         cl.viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
  260.     }
  261.     
  262.     up = CL_KeyState (&in_lookup);
  263.     down = CL_KeyState(&in_lookdown);
  264.     
  265.     cl.viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
  266.     cl.viewangles[PITCH] += speed*cl_pitchspeed->value * down;
  267. }
  268.  
  269. /*
  270. ================
  271. CL_BaseMove
  272.  
  273. Send the intended movement message to the server
  274. ================
  275. */
  276. void CL_BaseMove (usercmd_t *cmd)
  277. {    
  278.     CL_AdjustAngles ();
  279.     
  280.     memset (cmd, 0, sizeof(*cmd));
  281.     
  282.     VectorCopy (cl.viewangles, cmd->angles);
  283.     if (in_strafe.state & 1)
  284.     {
  285.         cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
  286.         cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
  287.     }
  288.  
  289.     cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
  290.     cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
  291.  
  292.     cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
  293.     cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
  294.  
  295.     if (! (in_klook.state & 1) )
  296.     {    
  297.         cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
  298.         cmd->forwardmove -= cl_forwardspeed->value * CL_KeyState (&in_back);
  299.     }    
  300.  
  301. //
  302. // adjust for speed key / running
  303. //
  304.     if ( (in_speed.state & 1) ^ (int)(cl_run->value) )
  305.     {
  306.         cmd->forwardmove *= 2;
  307.         cmd->sidemove *= 2;
  308.         cmd->upmove *= 2;
  309.     }    
  310. }
  311.  
  312. void CL_ClampPitch (void)
  313. {
  314.     float    pitch;
  315.  
  316.     pitch = SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
  317.     if (pitch > 180)
  318.         pitch -= 360;
  319.  
  320.     if (cl.viewangles[PITCH] + pitch < -360)
  321.         cl.viewangles[PITCH] += 360; // wrapped
  322.     if (cl.viewangles[PITCH] + pitch > 360)
  323.         cl.viewangles[PITCH] -= 360; // wrapped
  324.  
  325.     if (cl.viewangles[PITCH] + pitch > 89)
  326.         cl.viewangles[PITCH] = 89 - pitch;
  327.     if (cl.viewangles[PITCH] + pitch < -89)
  328.         cl.viewangles[PITCH] = -89 - pitch;
  329. }
  330.  
  331. /*
  332. ==============
  333. CL_FinishMove
  334. ==============
  335. */
  336. void CL_FinishMove (usercmd_t *cmd)
  337. {
  338.     int        ms;
  339.     int        i;
  340.  
  341. //
  342. // figure button bits
  343. //    
  344.     if ( in_attack.state & 3 )
  345.         cmd->buttons |= BUTTON_ATTACK;
  346.     in_attack.state &= ~2;
  347.     
  348.     if (in_use.state & 3)
  349.         cmd->buttons |= BUTTON_USE;
  350.     in_use.state &= ~2;
  351.  
  352.     if (anykeydown && cls.key_dest == key_game)
  353.         cmd->buttons |= BUTTON_ANY;
  354.  
  355.     // send milliseconds of time to apply the move
  356.     ms = cls.frametime * 1000;
  357.     if (ms > 250)
  358.         ms = 100;        // time was unreasonable
  359.     cmd->msec = ms;
  360.  
  361.     CL_ClampPitch ();
  362.     for (i=0 ; i<3 ; i++)
  363.         cmd->angles[i] = ANGLE2SHORT(cl.viewangles[i]);
  364.  
  365.     cmd->impulse = in_impulse;
  366.     in_impulse = 0;
  367.  
  368. // send the ambient light level at the player's current position
  369.     cmd->lightlevel = (byte)cl_lightlevel->value;
  370. }
  371.  
  372. /*
  373. =================
  374. CL_CreateCmd
  375. =================
  376. */
  377. usercmd_t CL_CreateCmd (void)
  378. {
  379.     usercmd_t    cmd;
  380.  
  381.     frame_msec = sys_frame_time - old_sys_frame_time;
  382.     if (frame_msec < 1)
  383.         frame_msec = 1;
  384.     if (frame_msec > 200)
  385.         frame_msec = 200;
  386.     
  387.     // get basic movement from keyboard
  388.     CL_BaseMove (&cmd);
  389.  
  390.     // allow mice or other external controllers to add to the move
  391.     IN_Move (&cmd);
  392.  
  393.     CL_FinishMove (&cmd);
  394.  
  395.     old_sys_frame_time = sys_frame_time;
  396.  
  397. //cmd.impulse = cls.framecount;
  398.  
  399.     return cmd;
  400. }
  401.  
  402.  
  403. void IN_CenterView (void)
  404. {
  405.     cl.viewangles[PITCH] = -SHORT2ANGLE(cl.frame.playerstate.pmove.delta_angles[PITCH]);
  406. }
  407.  
  408. /*
  409. ============
  410. CL_InitInput
  411. ============
  412. */
  413. void CL_InitInput (void)
  414. {
  415.     Cmd_AddCommand ("centerview",IN_CenterView);
  416.  
  417.     Cmd_AddCommand ("+moveup",IN_UpDown);
  418.     Cmd_AddCommand ("-moveup",IN_UpUp);
  419.     Cmd_AddCommand ("+movedown",IN_DownDown);
  420.     Cmd_AddCommand ("-movedown",IN_DownUp);
  421.     Cmd_AddCommand ("+left",IN_LeftDown);
  422.     Cmd_AddCommand ("-left",IN_LeftUp);
  423.     Cmd_AddCommand ("+right",IN_RightDown);
  424.     Cmd_AddCommand ("-right",IN_RightUp);
  425.     Cmd_AddCommand ("+forward",IN_ForwardDown);
  426.     Cmd_AddCommand ("-forward",IN_ForwardUp);
  427.     Cmd_AddCommand ("+back",IN_BackDown);
  428.     Cmd_AddCommand ("-back",IN_BackUp);
  429.     Cmd_AddCommand ("+lookup", IN_LookupDown);
  430.     Cmd_AddCommand ("-lookup", IN_LookupUp);
  431.     Cmd_AddCommand ("+lookdown", IN_LookdownDown);
  432.     Cmd_AddCommand ("-lookdown", IN_LookdownUp);
  433.     Cmd_AddCommand ("+strafe", IN_StrafeDown);
  434.     Cmd_AddCommand ("-strafe", IN_StrafeUp);
  435.     Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
  436.     Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
  437.     Cmd_AddCommand ("+moveright", IN_MoverightDown);
  438.     Cmd_AddCommand ("-moveright", IN_MoverightUp);
  439.     Cmd_AddCommand ("+speed", IN_SpeedDown);
  440.     Cmd_AddCommand ("-speed", IN_SpeedUp);
  441.     Cmd_AddCommand ("+attack", IN_AttackDown);
  442.     Cmd_AddCommand ("-attack", IN_AttackUp);
  443.     Cmd_AddCommand ("+use", IN_UseDown);
  444.     Cmd_AddCommand ("-use", IN_UseUp);
  445.     Cmd_AddCommand ("impulse", IN_Impulse);
  446.     Cmd_AddCommand ("+klook", IN_KLookDown);
  447.     Cmd_AddCommand ("-klook", IN_KLookUp);
  448.  
  449.     cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
  450. }
  451.  
  452.  
  453.  
  454. /*
  455. =================
  456. CL_SendCmd
  457. =================
  458. */
  459. void CL_SendCmd (void)
  460. {
  461.     sizebuf_t    buf;
  462.     byte        data[128];
  463.     int            i;
  464.     usercmd_t    *cmd, *oldcmd;
  465.     usercmd_t    nullcmd;
  466.     int            checksumIndex;
  467.  
  468.     // build a command even if not connected
  469.  
  470.     // save this command off for prediction
  471.     i = cls.netchan.outgoing_sequence & (CMD_BACKUP-1);
  472.     cmd = &cl.cmds[i];
  473.     cl.cmd_time[i] = cls.realtime;    // for netgraph ping calculation
  474.  
  475.     *cmd = CL_CreateCmd ();
  476.  
  477.     cl.cmd = *cmd;
  478.  
  479.     if (cls.state == ca_disconnected || cls.state == ca_connecting)
  480.         return;
  481.  
  482.     if ( cls.state == ca_connected)
  483.     {
  484.         if (cls.netchan.message.cursize    || curtime - cls.netchan.last_sent > 1000 )
  485.             Netchan_Transmit (&cls.netchan, 0, data);    
  486.         return;
  487.     }
  488.  
  489.     // send a userinfo update if needed
  490.     if (userinfo_modified)
  491.     {
  492.         CL_FixUpGender();
  493.         userinfo_modified = false;
  494.         MSG_WriteByte (&cls.netchan.message, clc_userinfo);
  495.         MSG_WriteString (&cls.netchan.message, Cvar_Userinfo() );
  496.     }
  497.  
  498.     SZ_Init (&buf, data, sizeof(data));
  499.  
  500.     if (cmd->buttons && cl.cinematictime > 0 && !cl.attractloop 
  501.         && cls.realtime - cl.cinematictime > 1000)
  502.     {    // skip the rest of the cinematic
  503.         SCR_FinishCinematic ();
  504.     }
  505.  
  506.     // begin a client move command
  507.     MSG_WriteByte (&buf, clc_move);
  508.  
  509.     // save the position for a checksum byte
  510.     checksumIndex = buf.cursize;
  511.     MSG_WriteByte (&buf, 0);
  512.  
  513.     // let the server know what the last frame we
  514.     // got was, so the next message can be delta compressed
  515.     if (cl_nodelta->value || !cl.frame.valid || cls.demowaiting)
  516.         MSG_WriteLong (&buf, -1);    // no compression
  517.     else
  518.         MSG_WriteLong (&buf, cl.frame.serverframe);
  519.  
  520.     // send this and the previous cmds in the message, so
  521.     // if the last packet was dropped, it can be recovered
  522.     i = (cls.netchan.outgoing_sequence-2) & (CMD_BACKUP-1);
  523.     cmd = &cl.cmds[i];
  524.     memset (&nullcmd, 0, sizeof(nullcmd));
  525.     MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
  526.     oldcmd = cmd;
  527.  
  528.     i = (cls.netchan.outgoing_sequence-1) & (CMD_BACKUP-1);
  529.     cmd = &cl.cmds[i];
  530.     MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  531.     oldcmd = cmd;
  532.  
  533.     i = (cls.netchan.outgoing_sequence) & (CMD_BACKUP-1);
  534.     cmd = &cl.cmds[i];
  535.     MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  536.  
  537.     // calculate a checksum over the move commands
  538.     buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
  539.         buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
  540.         cls.netchan.outgoing_sequence);
  541.  
  542.     //
  543.     // deliver the message
  544.     //
  545.     Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);    
  546. }
  547.  
  548.  
  549.